package org.spdata.tsdb.coder;

import java.io.ByteArrayOutputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.LinkedTransferQueue;

import org.spdata.utils.ByteUtils;
import org.spdata.utils.ListUtils;

/**
 * 递增整数序列（如：时间序列）编码器
 */
public class IncreasingIntArrayCoder {
	public int[] decode(byte[] input) {
		List<Integer> list = new ArrayList<Integer>();
		int first = ByteUtils.changeBytesToInt(input[0],input[1]);
		list.add(first);
		
		//有多少去重段落
		int sectionCount = input[2];
		if(sectionCount<0) {
			sectionCount = 0x7F & sectionCount;
			int countLow = input[3];
			sectionCount = ByteUtils.changeBytesToInt((byte)sectionCount,(byte)countLow);
		}
		int sectionsStart = 3;
		if(sectionCount>127) {
			sectionsStart = 4;
		}

		//从sectionsStart开始解析去重段落
		List<Map<String,Integer>> sections = new ArrayList<Map<String,Integer>>();
		for(int i=0;i<sectionCount;i++) {
			Map<String,Integer> section = RepeatIntCoder.decode(input, sectionsStart, 6);
			sections.add(section);
			sectionsStart+=6;
		}
		
		//解码其他整数
		java.util.Queue<Integer> rest = new LinkedTransferQueue<Integer>();
		if(sectionsStart<input.length) {
			Integer v = null;
			byte byteSize = input[sectionsStart];sectionsStart++;
			if(byteSize==1 ) {
				for(int i=sectionsStart;i<input.length;i++) {
					v = 0x7F & input[i];
					rest.add(v);
				}
			}else if(byteSize==2){
				for(int i=sectionsStart;i<input.length;i+=2) {
					v = ByteUtils.changeBytesToInt(input[i],input[i+1]);
					rest.add(v);
				}
			}else {
				throw new RuntimeException("非去重编码的整数长度不合法,size="+byteSize);
			}
			
		}
		
		List<Integer> deltas = new ArrayList<Integer>();
		
 		for(Map<String,Integer> section:sections) {
			Integer value = section.get("value");
			Integer from = section.get("from");
			Integer count = section.get("count");
			ListUtils.expandList(deltas, from+count-1);
			
			for(int i=0;i<count;i++) {
				deltas.set(from+i, value);
			}
		}
 		for(int i=0;i<deltas.size();i++) {
 			Integer delta = deltas.get(i);
 			if(delta==null) {
 				Integer v = rest.poll();
 				deltas.set(i, v);
 			}
 		}
 		while(rest.size()>0) {
 			deltas.add(rest.poll());
 		}
 	
 		//反delta解码
 		int pre = list.get(0);
 		for(Integer delta : deltas) {
 			if(delta==null)
 				System.out.println();
 			int cur = pre + delta;
 			pre = cur;
 			list.add(cur);
 		}
		
		int[] r = new int[list.size()];
		int i=0;
		for(Integer one:list) {
			r[i] = one.intValue();
			i++;
		}
		return r;
	}
	public byte[] encode(int[] input) {
		ByteArrayOutputStream output = new ByteArrayOutputStream();
		output.write(ByteUtils.changeIntTo2Bytes(input[0]), 0, 2);
		
		
		//求各值之间差,delta[n] 是 input[n+1]-input[n]的差
		int[] delta = new int[input.length-1];
		for(int i=0;i<input.length;i++) {
			if(i>0) {
				delta[i-1] = input[i]-input[i-1];
			}
		}
		//对差值进行等值分组
		List<RepeatIntCoder> sections = new ArrayList<RepeatIntCoder>();
		RepeatIntCoder currentSection = null;
		for(int i=0;i<delta.length;i++) {
			if(currentSection==null) {
				currentSection = new RepeatIntCoder(delta[i],i);
				sections.add(currentSection);
			}else {
				if(delta[i] == currentSection.getValue().intValue()) {
					currentSection.setEnd(i);
				}else {
					currentSection = new RepeatIntCoder(delta[i],i);
					sections.add(currentSection);
				}
				
			}
		}
		
		//统计可以去重编码的段落
		int count = 0;
		for(RepeatIntCoder section:sections) {
			if(section.getEnd()-section.getFrom()>5) {
				count ++;
			}
		}
		if(count>127) {
			int v = 0x8000 | count;
			output.write(ByteUtils.changeIntTo2Bytes(v),0,2);
		}else {
			output.write(count);
		}
		
		List<Integer> unEncoded = new ArrayList<Integer>();
		for(RepeatIntCoder section:sections) {
			if(section.getEnd()-section.getFrom()>5) {
				byte[] encoded = section.encode();
				output.write(encoded,0,encoded.length);
			}else {
				for(int i=section.getFrom();i<=section.getEnd();i++) {
					unEncoded.add(section.getValue());
				}
			}
		}
		
		//对不能去重编码的其他整数进行编码
		if(unEncoded.size()>0) {
			int max = this.calcMax(unEncoded);
			int byteNum = 0;
			if(max<128) {
				byteNum = 1;
			}else if(max<0x7FFF){
				byteNum = 2;
			}else {
				throw new RuntimeException("存在大于0x7FFF的差值，无法编码");
			}
			output.write(byteNum);
			if(byteNum==1)
				for(Integer v : unEncoded) {
					output.write(v);
				}
			else {
				for(Integer v : unEncoded) {
					output.write(ByteUtils.changeIntTo2Bytes(v),0,2);
				}
			}
		}
		return output.toByteArray();
		
	}
	
	
	
	/**
	 * 求整型序列的最大值绝对值
	 * @param list
	 * @return
	 */
	private int calcMax(List<Integer> list) {
		Integer max  = null;
		for(Integer one:list) {
			if(max == null) {
				max = one;
			}else if(one>max.intValue()){
				max = one;
			}
		}
		return max;
	}
	
	
	
	public static void main(String[] args) {
		test0();
		test1();
	}
	
	public static void test0() {
		
	}
	
	public static void test1() {
		
	}
}
